package sheep.view.Component;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.GrayFilter;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.JCheckBox;
import sheep.model.Calendrier;

//==========================================================================

public class CalendarCellRenderer extends JPanel implements ListCellRenderer {
  
  private Adapter binding;
  private final Border noFocusBorder;
  private Color evenRowColor;
  private Color oddRowColor;
  private Color messageColor;
  private Font nameLabelFont;
  private ImageIcon defaultCalendarIcon;
  private ImageIcon defaultOfflineCalendarIcon;
  private final Map<ImageIcon, ImageIcon> onlineCalendarIcons;
  private final Map<ImageIcon, ImageIcon> offlineCalendarIcons;
  private JLabel nameLabel;
  private JLabel messageLabel;
  private JLabel CalendarLabel;
  private Dimension CalendarIconSize = new Dimension(32, 32);
  private JCheckBox checkbox;
  private RoundedBox roundedBox;
  private Object value;
     
  //==========================================================================
  
  //Methode qui construit le cell
  public Component getListCellRendererComponent(JList jList, Object value, 
          int index, boolean isSelected, boolean hasFocus) {

    setComponentOrientation(jList.getComponentOrientation());
    this.value = value;
    // On defini la couleur du fond
    if (isSelected) {
      // Normal pour les selections
      setBackground(jList.getSelectionBackground());
      setForeground(jList.getSelectionForeground());
    }
    else {
      // On paint 1 bande sur 2
      setBackground(((index & 0x1) == 1) ? evenRowColor : oddRowColor);
      setForeground(jList.getForeground());
    }
        
    // Definition du bord
    Border border = null;
    if (hasFocus) {
      if (isSelected)
        border = UIManager.getBorder("List.focusSelectedCellHighlightBorder");
       if (border == null) 
           border = UIManager.getBorder("List.focusCellHighlightBorder");
    }else
        border = noFocusBorder;
      
    setBorder(border);
    // On recupere le calendrier de la case
    Adapter adapter = getAdapter(value);
    setToolTipText(adapter.getToolTipText());
    roundedBox.setColor(adapter.getColor());
    // Selon le status on coche la checkBox
    switch (adapter.getStatus()) {
	case SELECTED: checkbox.setSelected(true);break;
	case NOT_SELECTED: checkbox.setSelected(false);break;
    }
    // Affiche le nom du calendrier
    String name = adapter.getName();
    nameLabel.setText((name == null) ? "" : name);
    nameLabel.setForeground(getForeground());
    nameLabel.setEnabled(adapter.getStatus() != Adapter.Status.NOT_SELECTED);
    // Affiche le message si il existe et que l'on est select
    String msg = adapter.getMessage();
    msg = (msg != null) ? msg.trim() : "";
    if ((msg.length() == 0) || ((Calendrier)adapter.getValue()).isDisplay()) 	    
      messageLabel.setVisible(false);
    else  
      messageLabel.setVisible(true);
    // Affiche l'ampoule
    Icon CalendarIcon = (!adapter.isActif() ) ?
        offlineCalendarIcon(adapter.getCalendarIcon()) :
	onlineCalendarIcon(adapter.getCalendarIcon()) ;
    CalendarLabel.setIcon(CalendarIcon);
    CalendarLabel.setBackground(getBackground());
    return this;
  }

  // Impose la taille de l'icone
  public Dimension getCalendarIconSize() {
    return new Dimension(CalendarIconSize);
  }
    
  public void setCalendarIconSize(Dimension size) {
    if ((size == null) || (size.width < 0) || (size.height < 0))
      throw new IllegalArgumentException("invalid size");
    this.CalendarIconSize = new Dimension(size);
  }

  public void setSelected( boolean selected){
    checkbox.setSelected(selected);
  }
 
  public boolean isSelected(  ){
    return checkbox.isSelected();
  }
   
  // Creer l'image à la bonne taille  
  private ImageIcon onlineCalendarIcon(ImageIcon adapterCalendarIcon) {
    if (adapterCalendarIcon == null) 
      return defaultCalendarIcon;
    else {
      ImageIcon CalendarIcon = onlineCalendarIcons.get(adapterCalendarIcon);
      if (CalendarIcon != null) 
		return CalendarIcon; 
      else {		
        Dimension maxIconSize = getCalendarIconSize();	
        int iconWidth = adapterCalendarIcon.getIconWidth();
        int iconHeight = adapterCalendarIcon.getIconHeight();
        if ((iconWidth > maxIconSize.width) || (iconHeight > maxIconSize.height)) {
          double xScale = maxIconSize.getWidth() / (double)iconWidth;
          double yScale = maxIconSize.getHeight() / (double)iconHeight;
          double scale = Math.min(xScale, yScale);
          int scaledWidth = (int)(scale * (double)iconWidth);
          int scaledHeight = (int)(scale * (double)iconHeight);
          int flags = Image.SCALE_SMOOTH;
          Image scaledCalendarImage = 
			adapterCalendarIcon.getImage().getScaledInstance(scaledWidth, scaledHeight, flags);
		    CalendarIcon = new ImageIcon(scaledCalendarImage);	
        }
        onlineCalendarIcons.put(adapterCalendarIcon, CalendarIcon);
        return CalendarIcon;
      }
    }  
  }

  private ImageIcon createOfflineCalendarIcon(ImageIcon icon) {
    return new ImageIcon(GrayFilter.createDisabledImage(icon.getImage()));
  }

  ImageIcon offlineCalendarIcon(ImageIcon adapterCalendarIcon) {
    if (adapterCalendarIcon == null) 
      return defaultOfflineCalendarIcon;
    else {	    
      ImageIcon CalendarIcon = offlineCalendarIcons.get(adapterCalendarIcon);	    
      if (CalendarIcon != null) 		
        return CalendarIcon;	    	    
      else {		
        ImageIcon onlineCalendarIcon = onlineCalendarIcon(adapterCalendarIcon);		
        CalendarIcon = createOfflineCalendarIcon(onlineCalendarIcon);		
        offlineCalendarIcons.put(adapterCalendarIcon, CalendarIcon);		
        return CalendarIcon;	    
      }	
    }  
  }
   
  //==========================================================================
  
  public CalendarCellRenderer(Adapter binding) {	
    super(new GridBagLayout());	
    this.binding = binding;	
    onlineCalendarIcons = new HashMap<ImageIcon, ImageIcon>();	
    offlineCalendarIcons = new HashMap<ImageIcon, ImageIcon>();	
    noFocusBorder = new EmptyBorder(1, 1, 1, 1);	
    setBorder(noFocusBorder);	
    evenRowColor = Color.white;	
    oddRowColor = new Color(237, 243, 255);	
    messageColor = new Color(170, 170, 170);
	
    defaultCalendarIcon = new ImageIcon(getClass().getResource("/resources/icons/" + "compose-mail_01.png"));	
    defaultOfflineCalendarIcon = createOfflineCalendarIcon(defaultCalendarIcon);
	
    nameLabel = new JLabel("Name");	
    messageLabel = new JLabel("one line message");	
    CalendarLabel = new JLabel(defaultCalendarIcon);        
    checkbox = new JCheckBox();             
    checkbox.setOpaque(false);            
	
    nameLabelFont = nameLabel.getFont().deriveFont(12.0f).deriveFont(Font.BOLD);	
    nameLabel.setFont(nameLabelFont);	
    messageLabel.setForeground(messageColor);
     
    roundedBox = new RoundedBox(50,30,Color.WHITE);       
    roundedBox.setBorder(BorderFactory.createEmptyBorder(0, 50, 0, 50));
        
    BorderLayout borderLayout = new BorderLayout();        
    borderLayout.setHgap(20);	
    setLayout( borderLayout);        
    add(checkbox, BorderLayout.WEST);        
    add(CalendarLabel, BorderLayout.EAST);        
       
    JPanel tempPanel = new JPanel(new BorderLayout());       
    tempPanel.setOpaque(false);	
    tempPanel.add(nameLabel, BorderLayout.CENTER);      
    tempPanel.add(messageLabel, BorderLayout.SOUTH);       
    tempPanel.add(roundedBox, BorderLayout.EAST);        
    add (tempPanel, BorderLayout.CENTER);      
  }
    
  public CalendarCellRenderer() {	
    this(new Adapter());    
  }
   
  public Adapter getAdapter() { return binding; }
  
  public void setAdapter(Adapter binding) {	
    if (binding == null) 	    
      throw new IllegalArgumentException("null binding");	
    this.binding = binding;    
  }
      
  public final Adapter getAdapter(Object value) {	
    Adapter adapter = getAdapter();	
    adapter.setValue(value);	
    return adapter;    
  }

  //==========================================================================
    
  public static class Adapter {
	
    public enum Status {SELECTED, NOT_SELECTED};	
    private Object value;
	
    public Object getValue() { return value; }	
    public void setValue(Object value) { this.value = value; }
	
    public String     getName()         {return "Anonyme"; }   
    public Status     getStatus()       {return Status.NOT_SELECTED; }	
    public String     getMessage()      {return "Definir le nom SVP"; }  
    public Color      getColor ()       {return null;}
    public boolean    isActif()         {return true;}	
    public ImageIcon  getCalendarIcon() { return null; }
    public String     getToolTipText()  {return getName() + " " + getStatus(); }
  }
        
  public static class CalendarAdapter extends CalendarCellRenderer.Adapter {
    
    private final Map<URL, ImageIcon> iconCache = new HashMap<URL, ImageIcon>();	
    private Calendrier getCalendar() { return (Calendrier)getValue(); }
    
    @Override	
    public String getName() { return getCalendar().getName(); }
    
    @Override	
    public Status getStatus() { return getCalendar().getStatus(); }       
    public void setStatus(Status status) { getCalendar().setStatus(status); }
    
    @Override	
    public String getMessage() { return getCalendar().getMessage(); }
    
    @Override       
    public Color getColor (){return getCalendar().getColor();}
          
    @Override
    public boolean isActif(){return getCalendar().isCurrent();   }
    
    @Override
    public ImageIcon getCalendarIcon() { 	    
      URL url = getCalendar().getBuddyIconURL();	    
      if (url == null) 		
        return null; 	    
      ImageIcon icon = iconCache.get(url);	    
      if (icon != null) 		
        return icon;	    	   
      icon = new ImageIcon(url);	    
      iconCache.put(url, icon);	    
      return icon;	
    }   
  }
    
  //==========================================================================

}

//==========================================================================
